#pragma once
#include "../stdafx.h"


#define					PACKET_OTHER		0
#define					PACKET_BYTE			1
#define					PACKET_BOOL			2
#define					PACKET_DOUBLE		3
#define					PACKET_FLOAT		4
#define					PACKET_LONG			5
#define					PACKET_ULONG		6
#define					PACKET_ULLONG		7
#define					PACKET_STRING		8
#define					PACKET_16STRING		9
#define					PACKET_BYTEARRAY	10

/*
*		CPackets, within the stream, take the format of TYPE(BYTE)|SUBTYPE(BYTE)|SIZE(UNSIGNED INT)|PROCESS(UNSIGNED INT)|PAYLOAD(SIZE*BYTE)
*					with the functions below you are only modifying the payload section
*/


class CPacket
{
public:
	CPacket();
	CPacket(BYTE id);
	CPacket(SOCKET s);
	~CPacket();

public:			// interface functions

/* packing data */

	void				packType(BYTE type, unsigned int size);
	void				pack(BYTE value);
	void				pack(bool value);
	void				pack(double value);
	void				pack(float value);
	void				pack(long value);
	void				pack(unsigned long value);
	void				pack(unsigned long long value);
	void				pack(string value);
	void				pack(char* value, unsigned int size);

/* unpacking data */

	BYTE				unpackByte();
	bool				unpackBoolean();
	double				unpackDouble();
	float				unpackFloat();
	long				unpackLong();
	unsigned long		unpackULong();
	unsigned long long	unpackULLong();
	string				unpackString();
	void				unpackByteArray(char *value, unsigned int &size);

/* testing data */

	BYTE				getTypeOfNextItem();
	bool				isNextItemA(BYTE type);


/* packet format routines */

	void				compressPacket();
	void				decompressPacket();
	void				encryptPacket(void* key);
	void				decryptPacket(void* key);

/* packet transmission */

	bool				transmitPacket(SOCKET s);

/* accessors */
	BYTE				getPacketType() { return mPacketType; };
	void				setSubtype(BYTE type) { mSubType = type; };
	void				setTargetProcess(unsigned int prc) { mTargetProcess = prc; }

protected:

	BYTE				mPacketType;
	BYTE				mSubType;
	unsigned int		mTargetProcess;
	unsigned int		mSize;
	unsigned int		mSeek;
	char*				mBuffer;
	bool				mCompressed;
	bool				mEncrypted;
	void				packLiteral(char* value, unsigned int size);
	void				unpackLiteral(char* value, unsigned int size);
	void				unpackItemHeader(BYTE &type, unsigned int &size);

private:
	bool				safeSend(SOCKET sock,const char* data,int size);
	int					safeRecv(SOCKET s, char* &buffer, unsigned int size);
	bool				isReadable(SOCKET sock);
	bool				isWriteable(SOCKET sock);
};